package com.example.demo.service;

import com.example.demo.domain.result.helper.CourseGrade;
import com.example.demo.domain.result.ExamInfoResult;
import com.example.demo.domain.result.GradesResult;
import com.example.demo.exception.PasswordErrorException;
import com.example.demo.utils.HbutEtcLoginUtil;
import com.example.demo.utils.HbutLoginUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 查询学生成绩
 * @author hongjinhui
 */
@Slf4j
@Service
public class GradesService {
    private final String GRADE_URL = "Index";
    private final String EXAM_INFO_URL = "ViewBukaoSchedule";
    /**
     * 根据学期查询成绩
     */
    public GradesResult getGrades(String username, String password, String termId) throws PasswordErrorException, IOException {
        Document document = HbutLoginUtil.getStuGradesDoc(username, password, termId, GRADE_URL);
        GradesResult gradesResult = new GradesResult();
        List<String> termIds = new ArrayList<>();
        // 获取学期信息
        Element select = document.getElementById("SemesterName");
        Elements options = select.select("option");
        for (Element option : options) {
            termIds.add(option.attr("value"));
        }
        gradesResult.setTermIds(termIds);
        gradesResult.setCurrentTermId(termIds.get(0));
        // 获取绩点
        gradesResult.setAverageGradePoint(Double.parseDouble(document.select("#mainContent > div:nth-child(5)").text().split(" ")[1]));
        // 获取详细课程成绩信息
        Elements table = document.getElementsByClass("table-list");
        Elements trs = table.select("tr");
        List<CourseGrade> courseGradeList = new ArrayList<>();
        boolean isHeader = true;
        for (Element tr : trs) {
            if (isHeader) {
                isHeader = false; continue;
            }
            CourseGrade courseGrade = new CourseGrade();
            Elements tds = tr.select("td");
            int flag = 0;
            for (Element td : tds) {
                String val = td.ownText();
                if (flag == 0) {
                    courseGrade.setTaskId(val);
                } else if (flag == 1) {
                    courseGrade.setCourseName(val);
                } else if (flag == 2) {
                    courseGrade.setCourseType(val);
                } else if (flag == 3) {
                    courseGrade.setGradePoint("".equals(val)? null:Double.parseDouble(val));
                } else if (flag == 4) {
                    courseGrade.setCredit("".equals(val)? null:Double.parseDouble(val));
                } else if (flag == 5) {
                    courseGrade.setUsualGrades(val==null || "".equals(val)? "未公布":val);
                } else if (flag == 6) {
                    courseGrade.setFinalGrades(val==null || "".equals(val)? "未公布":val);
                } else if (flag == 7) {
                    courseGrade.setGradesWeight(val);
                } else if (flag == 8) {
                    courseGrade.setTotalGrades(val==null || "".equals(val)? "未公布":val);
                } else if (flag == 9) {
                    Elements label = td.select("label");
                    courseGrade.setMakeUpExamState(label.first()==null?null:label.first().ownText());
                } else if (flag == 10) {
                    Elements label = td.select("label");
                    courseGrade.setPublicGrades(label.first()==null?null:label.first().ownText());
                } else {
                    courseGrade.setCourseEvaluation(val);
                }
                ++flag;
            }
            courseGradeList.add(courseGrade);
        }
        gradesResult.setDetailedGrades(courseGradeList);
        //计算当前学期的绩点
        double sum1 = 0, sum2 = 0;
        for (CourseGrade courseGrade : courseGradeList) {
            sum1 += (courseGrade.getGradePoint()==null?0:courseGrade.getGradePoint())* (courseGrade.getCredit()==null?0:courseGrade.getCredit());
            sum2 += (courseGrade.getCredit()==null?0:courseGrade.getCredit());
        }
        gradesResult.setCurrentTermGradePoint(Double.parseDouble(String.format("%.4f", sum1/sum2)));

        return gradesResult;
    }

    /**
     * 爬取考试信息
     */
    public List<ExamInfoResult> queryExamInfo(String username, String password) throws PasswordErrorException, IOException {
        Document document = HbutLoginUtil.getStuGradesDoc(username, password, "", EXAM_INFO_URL);
        Elements table = document.getElementsByClass("table-list");
        Elements trs = table.select("tr");
        List<ExamInfoResult> resultList = new ArrayList<>();
        boolean isHeader = true;
        for (Element tr : trs) {
            if (isHeader) {
                isHeader = false; continue;
            }
            Elements tds = tr.select("td");
            ExamInfoResult examInfoResult = new ExamInfoResult();
            if (tds.size() == 1) {
                return resultList;
            }
            int flag = 0;
            for (Element td : tds) {
                if (flag == 0) {
                    examInfoResult.setCourseName(td.ownText());
                } else {
                    examInfoResult.setExamPlaceAndTime(td.ownText());
                }
                ++flag;
            }
            resultList.add(examInfoResult);
        }
        return resultList;
    }
    public GradesResult getEtcGrade(String username, String password, String termId) throws PasswordErrorException, IOException {
        Map<String, List<CourseGrade>> mapGrade = new HashMap<>(10);
        Map<String, Double> mapGradePoint = new HashMap<>(10);
        List<String> termIds = new ArrayList<>(8);
        Double totalGradePoint  = 0D;
        int courseCount = 0;
        String result = HbutEtcLoginUtil.getEtcGradeResult(username, password);
        JSONObject jsonObject = JSONObject.fromObject(result);
        String lnList = jsonObject.getString("lnList");
        String[] cjLists = lnList.substring(1, lnList.length()-1).split("cjList");
        int len = cjLists.length;
        for (int i = 1; i < len; ++i) {
            Double currentTotalGradePoint  = 0D;
            int currentCourseCount = 0;
            String[] ids = cjLists[i].split("id");
            List<CourseGrade> listCourse = new ArrayList<>(64);
            String currentTermId = null;
            for (int j = 1; j < ids.length; ++j) {
                String id = "{" + "\"id" + ids[j];
                if (!(i == len-1 && j == ids.length-1)) {
                    id = id.substring(0, id.length()-3);
                }
                JSONObject cos = JSONObject.fromObject(id);
                String tmpTermId = cos.getString("id");
                currentTermId = JSONObject.fromObject(tmpTermId).getString("executiveEducationPlanNumber");
                CourseGrade courseGrade = new CourseGrade();
                courseGrade.setTaskId(cos.getString("classNo"));
                courseGrade.setCourseName(cos.getString("courseName"));
                courseGrade.setGradePoint(cos.getDouble("gradePointScore"));
                courseGrade.setCredit(cos.getDouble("credit"));
                courseGrade.setTotalGrades(cos.getString("courseScore"));
                ++courseCount;
                ++currentCourseCount;
                totalGradePoint += cos.getDouble("gradePointScore");
                currentTotalGradePoint += cos.getDouble("gradePointScore");
                listCourse.add(courseGrade);
            }
            termIds.add(currentTermId);
            mapGrade.put(currentTermId, listCourse);
            mapGradePoint.put(currentTermId, Double.parseDouble(String.format("%.4f", currentTotalGradePoint/currentCourseCount)));
        }

        GradesResult gradesResult = new GradesResult();
        gradesResult.setTermIds(termIds);
        if ((termId == null || "".equals(termId)) && termIds.size() > 0) {
            String currentTermId = termIds.get(termIds.size()-1);
            gradesResult.setCurrentTermId(currentTermId);
            gradesResult.setDetailedGrades(mapGrade.get(currentTermId));
//            gradesResult.setCurrentTermGradePoint(mapGradePoint.get(currentTermId));
//            gradesResult.setAverageGradePoint(Double.parseDouble(String.format("%.4f", totalGradePoint/courseCount)));
        } else if (termIds.size() > 0){
            gradesResult.setCurrentTermId(termIds.get(termIds.size()-1));
            gradesResult.setDetailedGrades(mapGrade.get(termId));
//            gradesResult.setCurrentTermGradePoint(mapGradePoint.get(termId));
//            gradesResult.setAverageGradePoint(Double.parseDouble(String.format("%.4f", totalGradePoint/courseCount)));
        }
        return gradesResult;
    }
}

